//
//  MKUtils.m
//  SMG2
//
//  Created by 贾  on 2017/3/29.
//  Copyright © 2017年 XiaoGang. All rights reserved.
//

#import "MKUtils.h"
#import "MKHeader.h"

@implementation MKUtils



/**
 *	@brief	获取自身的属性
 *
 *	@param 	pronames 	保存属性名称
 *	@param 	protypes 	保存属性类型
 */
+ (void)getSelfPropertys:(NSMutableArray *)pronames protypes:(NSMutableArray *)protypes forClass:(Class)class
{
    unsigned int outCount = 0, i = 0;
    objc_property_t *properties = class_copyPropertyList(class, &outCount);
    
    for (i = 0; i < outCount; i++) {
        objc_property_t property = properties[i];
        NSString *propertyName = [NSString stringWithCString:property_getName(property) encoding:NSUTF8StringEncoding];
        
        //取消rowid 的插入 //子类 已重载的属性 取消插入
        if (propertyName.length == 0 || [propertyName isEqualToString:@"rowid"] ||
            [pronames indexOfObject:propertyName] != NSNotFound) {
            continue;
        }
        NSString *propertyType = [NSString stringWithCString:property_getAttributes(property) encoding:NSUTF8StringEncoding];
        
        ///过滤只读属性
        if ([propertyType rangeOfString:@",R,"].length > 0 || [propertyType hasSuffix:@",R"]) {
            NSString *firstWord = [[propertyName substringToIndex:1] uppercaseString];
            NSString *otherWord = [propertyName substringFromIndex:1];
            NSString *setMethodString = [NSString stringWithFormat:@"set%@%@:", firstWord, otherWord];
            SEL setSEL = NSSelectorFromString(setMethodString);
            ///有set方法就不过滤了
            if ([class instancesRespondToSelector:setSEL] == NO) {
                continue;
            }
        }
        
        /*
         c char
         i int
         l long
         s short
         d double
         f float
         @ id //指针 对象
         ...  BOOL 获取到的表示 方式是 char
         .... ^i 表示  int * 一般都不会用到
         */
        
        NSString *propertyClassName = nil;
        if ([propertyType hasPrefix:@"T@"]) {
            
            NSRange range = [propertyType rangeOfString:@","];
            if (range.location > 4 && range.location <= propertyType.length) {
                range = NSMakeRange(3, range.location - 4);
                propertyClassName = [propertyType substringWithRange:range];
                if ([propertyClassName hasSuffix:@">"]) {
                    NSRange categoryRange = [propertyClassName rangeOfString:@"<"];
                    if (categoryRange.length > 0) {
                        propertyClassName = [propertyClassName substringToIndex:categoryRange.location];
                    }
                }
            }
        }
        else if ([propertyType hasPrefix:@"T{"]) {
            NSRange range = [propertyType rangeOfString:@"="];
            if (range.location > 2 && range.location <= propertyType.length) {
                range = NSMakeRange(2, range.location - 2);
                propertyClassName = [propertyType substringWithRange:range];
            }
        }
        else {
            propertyType = [propertyType lowercaseString];
            if ([propertyType hasPrefix:@"ti"] || [propertyType hasPrefix:@"tb"]) {
                propertyClassName = @"int";
            }
            else if ([propertyType hasPrefix:@"tf"]) {
                propertyClassName = @"float";
            }
            else if ([propertyType hasPrefix:@"td"]) {
                propertyClassName = @"double";
            }
            else if ([propertyType hasPrefix:@"tl"] || [propertyType hasPrefix:@"tq"]) {
                propertyClassName = @"long";
            }
            else if ([propertyType hasPrefix:@"tc"]) {
                propertyClassName = @"char";
            }
            else if ([propertyType hasPrefix:@"ts"]) {
                propertyClassName = @"short";
            }
        }
        
        if ([LKDBUtils checkStringIsEmpty:propertyClassName]) {
            ///没找到具体的属性就放弃
            continue;
        }
        ///添加属性
        [pronames addObject:propertyName];
        [protypes addObject:propertyClassName];
    }
    free(properties);
    if ([class isContainParent] && [class superclass] != [NSObject class]) {
        [MKUtils getSelfPropertys:pronames protypes:protypes forClass:[class superclass]];
    }
}


//获取所有propertys
- (void)mutableString:(NSMutableString *)sb appendPropertyStringWithClass:(Class)clazz containParent:(BOOL)containParent
{
    if (clazz == [NSObject class]) {
        return;
    }
    unsigned int outCount = 0, i = 0;
    objc_property_t *properties = class_copyPropertyList(clazz, &outCount);
    for (i = 0; i < outCount; i++) {
        objc_property_t property = properties[i];
        NSString *propertyName = [NSString stringWithCString:property_getName(property) encoding:NSUTF8StringEncoding];
        [sb appendFormat:@" %@ : %@ \n", propertyName, [self valueForKey:propertyName]];
    }
    free(properties);
    if (containParent) {
        [self mutableString:sb appendPropertyStringWithClass:clazz.superclass containParent:containParent];
    }
}


/**
 *  MARK:--------------------递归收集InsertModel数组--------------------
 */
+(void) getInsertModelWithOutArr:(NSMutableArray*)outArr withModel:(MKObject*)model{
    [self getInsertModelWithOutArr:outArr withModel:model withDataModel:model];
}
+(void) getInsertModelWithOutArr:(NSMutableArray*)outArr withModel:(MKObject*)model withDataModel:(MKObject*)dataModel{
    //1,数据检查
    if (outArr == nil || model == nil || ![model isKindOfClass:[MKObject class]] || dataModel == nil || ![dataModel isKindOfClass:[MKObject class]]) {
        return;
    }
    //2,自身添加到outArr
    [outArr addObject:model];
    //3,父类型检查
    Class selfClass = [model class];
    Class supClass = [model superclass];
    if (supClass && selfClass != [NSObject class] && supClass != [NSObject class]) {
        //4,取父类的所有属性名;
        NSMutableArray *proNames = [[NSMutableArray alloc] init];
        NSMutableArray *proTypes = [[NSMutableArray alloc] init];
        [MKUtils getSelfPropertys:proNames protypes:proTypes forClass:supClass];
        //5,创建父类实例
        MKObject *supModel = [[supClass alloc] init];
        for (NSString *name in proNames) {
            if ([supModel respondsToSelector:NSSelectorFromString(name)]) {
                id value = [dataModel valueForKey:name];
                [supModel setValue:value forKey:name];
            }
        }
        //6,递归
        [self getInsertModelWithOutArr:outArr withModel:supModel withDataModel:dataModel];
    }
}


/**
 *  MARK:--------------------递归收集类继承图(子在前,父在后)--------------------
 */
+(NSMutableArray*) getClassLinkList:(Class)class{
    NSMutableArray *arr = [[NSMutableArray alloc] init];
    Class curClass = class;
    while (curClass && curClass != [NSObject class]) {
        [arr addObject:curClass];
        curClass = [curClass superclass];
    }
    return arr;
}

/**
 *  MARK:--------------------学习一条知识--------------------
 *  MKObject根表作了防重复;但子表未作(以后再决定作不作)(2017.04.07)
 */
+(void) insertSingleKnowledge:(MKObject*)model{
    if (model == nil) {
        return;
    }
    DB_MK *dbmk = [DB_MK sharedInstance];
    NSMutableArray *outArr = [[NSMutableArray alloc] init];
    [MKUtils getInsertModelWithOutArr:outArr withModel:model];

    for (int i = 0; i < outArr.count; i ++) {
        MKObject *item = outArr[outArr.count - i - 1];
        if ([item isMemberOfClass:[MKObject class]]) {
            MKObject *findOld = [MKObject searchSingleWithWhere:[DBUtils sqlWhere_K:@"name" V:item.name] orderBy:nil withDBHelper:dbmk];
            if (findOld) {
                model.rowid = findOld.rowid;//有重复则不重复存根值;
                dbmk.curMKObjectId = findOld.rowid;//使用本地rowid
            }else{
                [[item class] insertToDB:item withDBHelper:dbmk];//无重复则存储;
                dbmk.curMKObjectId = item.rowid;//使用新rowid
            }
        }else{
            [[item class] insertToDB:item withDBHelper:dbmk];//MKObject的子类(目前)随便存;
        }
    }
    dbmk.curMKObjectId = 0;
}

/**
 *  MARK:--------------------查询知识图谱简单的知识--------------------
 */
//某物属性
+(void) searchSingleKnowledge:(NSString*)objectName withProperty:(NSString*)property withDB:(LKDBHelper*)db withSuccess:(void(^)(MKObjectType type, id response))successBlock withError:(void(^)(NSString *errorCode))errorBlock{
    //解说例子,查找桃的"甜"味值
    //1,参数检查;
    if (db == nil || objectName == nil || property == nil) {
        if (errorBlock) {
            errorBlock(MK_PARAMS_ERROR);
        }
        return;
    }
    //2,查桃;
    MKObject *findMKObj = [MKObject searchSingleWithWhere:[DBUtils sqlWhere_K:@"name" V:objectName] orderBy:nil withDBHelper:db];
    if (findMKObj == nil) {
        if (errorBlock) {
            errorBlock(MK_NO_FIND);
        }
        return;
    }
    //3,查甜;
    MKObject *findSweet = [MKObject searchSingleWithWhere:[DBUtils sqlWhere_K:@"name" V:property] orderBy:nil withDBHelper:db];
    if (findSweet == nil) {
        if (errorBlock) {
            errorBlock(MK_NO_PROPERTY);
        }
        return;
    }
    
    //4,属性为抽象属性时;
    if (findSweet.type == MKObjectType_Abstract) {
        //5.3查甜是哪个表的哪个属性;
        MKAbstractObject *absSweet = [MKAbstractObject searchSingleWithWhere:[DBUtils sqlWhere_K:MKObjectId_ColumnName V:@(findSweet.rowid)] orderBy:nil withDBHelper:db];
        //5.4表类型;
        Class absSweetClass = NSClassFromString(absSweet.className);
        //5.5属性
        SEL absSweetProperty = NSSelectorFromString(absSweet.propertyName);
        //5.6到味道表中找桃的味道;
        MKObject *sweetClassModel = [absSweetClass searchSingleWithWhere:[DBUtils sqlWhere_K:MKObjectId_ColumnName V:@(findMKObj.rowid)] orderBy:nil withDBHelper:db];
        //5.7到桃的味道中找甜着值;
        if (sweetClassModel && [sweetClassModel respondsToSelector:absSweetProperty]) {
            id value = [sweetClassModel valueForKey:absSweet.propertyName];
            if (successBlock) {
                successBlock(MKObjectType_Abstract,value);
            }
            return;
        }
    }else if (findSweet.type == MKObjectType_Virtual) {
        //5.3查甜是哪个表的哪个属性;
        MKVirtualObject *virObj = [MKVirtualObject searchSingleWithWhere:[DBUtils sqlWhere_RowId:findSweet.rowid] orderBy:nil withDBHelper:db];
        //5.4表类型;
        Class virClass = NSClassFromString(virObj.className);
        //5.6到味道表中找桃的味道;
        MKObject *model = [virClass searchSingleWithWhere:[DBUtils sqlWhere_K:MKObjectId_ColumnName V:@(findMKObj.rowid)] orderBy:nil withDBHelper:db];
        //5.7到桃的味道中找甜着值;
        if (successBlock) {
            successBlock(MKObjectType_Virtual,model);
        }
        return;
    }else{
        if (errorBlock) {
            errorBlock(MK_NO_PROPERTY);
        }
        return;
    }
    if (errorBlock) {
        errorBlock(MK_OTHER_ERROR);
    }
}

//某物是否某物
+(BOOL) searchSingleKnowledge:(NSString*)objectName isName:(NSString*)isName{
    return true;//以后再写;
}

@end
